#include <jni.h>
#include <string>
#include <exception>
#include "header/md5.h"
#include "header/AES.h"

using namespace std;

unsigned char *aesKey = (unsigned char *) "ompoRfIdf$3XCFC8";
unsigned char *aesIv = (unsigned char *) "CDB!yNYFtWb5U37b";
/**
 * 最开始会运行此方法
 * @return
 */
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
    JNIEnv *env = NULL;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
        return JNI_ERR;
    }
    return JNI_VERSION_1_6;
}

jbyteArray charToJByteArray(JNIEnv *env, unsigned char *buf,int len) {
    jbyteArray array = env->NewByteArray(len);
    env->SetByteArrayRegion(array, 0, len, (jbyte *)buf);
    return array;
}

unsigned char* convertJByteArrayToChars(JNIEnv *env, jbyteArray bytearray)
{
    unsigned char *chars = NULL;
    jbyte *bytes;
    bytes = env->GetByteArrayElements(bytearray, 0);
    int chars_len = env->GetArrayLength(bytearray);
    chars = new unsigned char[chars_len + 1];
    memset(chars,0,chars_len + 1);
    memcpy(chars, bytes, chars_len);
    chars[chars_len] = 0;
    env->ReleaseByteArrayElements(bytearray, bytes, 0);
    return chars;
}


extern "C"
JNIEXPORT jstring JNICALL
Java_com_jsgt_jni_JniUtil_getSignKey(JNIEnv *env,jclass clazz, jstring code) {
    env->FindClass("com/jsgt/jni/JniCheck");
    //这里如果类找不到一定会崩溃，trycatch也没用.java层里也捕获不了这个异常
    const char *c_code = NULL;
    char buff[128] = {0};
    jboolean isCopy;    // 返回JNI_TRUE表示原字符串的拷贝，返回JNI_FALSE表示返回原字符串的指针
    c_code = env->GetStringUTFChars(code, &isCopy);

    sprintf(buff, "jsgt%swallet", c_code);
    env->ReleaseStringUTFChars(code, c_code);
    return env->NewStringUTF(buff);
}

extern "C"
JNIEXPORT jstring JNICALL
Java_com_jsgt_jni_JniUtil_getSecurityKey(JNIEnv *env,
                                         jclass clazz, jstring code) {
    env->FindClass("com/jsgt/jni/JniCheck");
    const char *c_code = NULL;
    char buff[128] = {0};
    jboolean isCopy;    // 返回JNI_TRUE表示原字符串的拷贝，返回JNI_FALSE表示返回原字符串的指针
    c_code = env->GetStringUTFChars(code, &isCopy);

    sprintf(buff, "%sHvwmCrBqUQNSTjJK", c_code);
    env->ReleaseStringUTFChars(code, c_code);
    return env->NewStringUTF(buff);
}

extern "C"
JNIEXPORT jstring JNICALL
Java_com_jsgt_jni_JniUtil_getAesKey(JNIEnv *env,
                                    jclass clazz) {
    env->FindClass("com/jsgt/jni/JniCheck");
    return env->NewStringUTF("ompoRfIdf$3XCFC8");
}

extern "C"
JNIEXPORT jstring JNICALL
Java_com_jsgt_jni_JniUtil_getAesIv(JNIEnv *env,
                                   jclass clazz) {
    env->FindClass("com/jsgt/jni/JniCheck");
    return env->NewStringUTF("CDB!yNYFtWb5U37b");
}

extern "C"
JNIEXPORT jstring JNICALL
Java_com_jsgt_jni_JniUtil_getSignKeyPwd(JNIEnv *env,jclass clazz, jstring code) {
    env->FindClass("com/jsgt/jni/JniCheck");
    //这里如果类找不到一定会崩溃，trycatch也没用.java层里也捕获不了这个异常
    const char *c_code = NULL;
    char buff[128] = {0};
    jboolean isCopy;    // 返回JNI_TRUE表示原字符串的拷贝，返回JNI_FALSE表示返回原字符串的指针
    c_code = env->GetStringUTFChars(code, &isCopy);

    sprintf(buff, "jsgt%swallet", c_code);
    env->ReleaseStringUTFChars(code, c_code);
    MD5* md5 = new MD5(buff);
    jstring result =  env->NewStringUTF(md5->toStr().c_str());
    delete md5;
    return result;
}

extern "C"
JNIEXPORT jstring JNICALL
Java_com_jsgt_jni_JniUtil_getSecurityKeyPwd(JNIEnv *env,
                                            jclass clazz, jstring code) {
    env->FindClass("com/jsgt/jni/JniCheck");
    const char *c_code = NULL;
    char buff[128] = {0};
    jboolean isCopy;    // 返回JNI_TRUE表示原字符串的拷贝，返回JNI_FALSE表示返回原字符串的指针
    c_code = env->GetStringUTFChars(code, &isCopy);
    sprintf(buff, "%sHvwmCrBqUQNSTjJK", c_code);
    env->ReleaseStringUTFChars(code, c_code);
    MD5* md5 = new MD5(buff);
    jstring result = env->NewStringUTF(md5->toStr().c_str());
    delete md5;
    return result;
}


extern "C"
JNIEXPORT jbyteArray JNICALL
Java_com_jsgt_jni_JniUtil_aesEncode(JNIEnv *env,
                                    jclass clazz, jbyteArray jArr) {

    unsigned char* uChar = convertJByteArrayToChars(env,jArr);
    AES* aes =  new AES(128);
    unsigned int outLen = 0;
    unsigned int inLen = sizeof(unsigned char)*(env->GetArrayLength(jArr));
    unsigned char *out = aes->EncryptCBC(uChar,inLen,aesKey,aesIv,outLen);
    jbyteArray result = charToJByteArray(env,out,outLen);
    delete out;
    delete aes;
    return result;
}

extern "C"
JNIEXPORT jbyteArray JNICALL
Java_com_jsgt_jni_JniUtil_aesDecode(JNIEnv *env,
                                    jclass clazz, jbyteArray jArr) {
    unsigned char* uChar = convertJByteArrayToChars(env,jArr);
    AES* aes = new AES(128);
    unsigned int inLen = sizeof(unsigned char)*(env->GetArrayLength(jArr));
    unsigned char *out = aes->DecryptCBC(uChar,inLen,aesKey,aesIv);
    int outLen = strlen((const char*)out);
    jbyteArray result =  charToJByteArray(env,out,outLen);
    delete out;
    delete aes;
    return result;
}